#include "model.h"
#include "core.h"
#include "log.h"

model::model()
{
	m_render = core::get_inst().get_render();
	m_vbuffer = 0;
	m_ibuffer = 0;
	m_meshes.clear();
	m_materials.clear();
	m_bones.clear();
	m_weights.clear();
	m_animations.clear();
	m_boneroot = 0;
	m_currani = 0;
}

model::~model()
{
	release();
}

void model::release()
{
	m_materials.clear();
	m_meshes.clear();
	m_weights.clear();
	m_bones.clear();
	m_animations.clear();

	if(m_vbuffer)
		delete m_vbuffer;
	if(m_ibuffer)
		delete m_ibuffer;
}

#ifdef _MSC_VER
#pragma pack(push,packing)
#pragma pack(1)
#endif

struct MS3DHeader
{
	char m_ID[10];
	int m_version;
};

struct MS3DVertex
{
	byte m_flags;
	float m_vertex[3];
	char m_boneID;
	byte m_refCount;
};

struct MS3DTriangle
{
	u16 m_flags;
	u16 m_vertexIndices[3];
	float m_vertexNormals[3][3];
	float m_s[3], m_t[3];
	byte m_smoothingGroup;
	byte m_groupIndex;
};

struct MS3DMaterial
{
	char m_name[32];
	float m_ambient[4];
	float m_diffuse[4];
	float m_specular[4];
	float m_emissive[4];
	float m_shininess;
	float m_transparency;
	byte m_mode;
	char m_texture[128];
	char m_alphamap[128];
};

struct MS3DJoint
{
	byte m_flags;
	char m_name[32];
	char m_parentName[32];
	float m_rotation[3];
	float m_translation[3];
	u16 m_numRotationKeyframes;
	u16 m_numTranslationKeyframes;
};

struct MS3DKeyframe
{
	float m_time;
	float m_parameter[3];
};

#pragma pack(pop,packing)

void model::load_ms3d(const char *_fname)
{
	release();

	file f;
	u32 fileSize = f.open(_fname);

	byte *pBuffer = new byte[fileSize];
	f.read(pBuffer,fileSize);
	f.close();

	const byte *pPtr = pBuffer;
	MS3DHeader *pHeader = (MS3DHeader*)pPtr;
	pPtr += sizeof(MS3DHeader);

	if(strncmp(pHeader->m_ID,"MS3D000000",10)!= 0)
		LOG_ERROR("Not a valid Milkshape3D model file.");

	if(pHeader->m_version<3||pHeader->m_version>4)
		LOG_ERROR("Unhandled file version. Only Milkshape3D Version 1.3 and 1.4 is supported.");

	u32 nVertices = *(u16*)pPtr; 
	vector3* pVertices = new vector3[nVertices];
	pPtr += sizeof(u16);

	m_min = vector3(1000000.0f,1000000.0f,1000000.0f);
	m_max = vector3(-1000000.0f,-1000000.0f,-1000000.0f);

	u32 i;
	for(i=0;i<nVertices;i++)
	{
		MS3DVertex *pVertex = (MS3DVertex*)pPtr;
		pVertices[i] = vector3(pVertex->m_vertex[0],pVertex->m_vertex[1],pVertex->m_vertex[2]);
		
		if(pVertices[i].x < m_min.x)
			m_min.x = pVertices[i].x;
		if(pVertices[i].x > m_max.x)
			m_max.x = pVertices[i].x;

		if(pVertices[i].y < m_min.y)
			m_min.y = pVertices[i].y;
		if(pVertices[i].y > m_max.y)
			m_max.y = pVertices[i].y;

		if(pVertices[i].z < m_min.z)
			m_min.z = pVertices[i].z;
		if(pVertices[i].z > m_max.z)
			m_max.z = pVertices[i].z;

		pPtr += sizeof(MS3DVertex);
	}

	u32 nTriangles = *(u16*)pPtr;
	mdl_triangle* pTriangles = new mdl_triangle[nTriangles];
	pPtr += sizeof(u16);

	for(i=0;i<nTriangles;i++)
	{
		MS3DTriangle *pTriangle = (MS3DTriangle*)pPtr;
		pTriangles[i].m_vertexes[0] = pTriangle->m_vertexIndices[0];
		pTriangles[i].m_vertexes[1] = pTriangle->m_vertexIndices[1];
		pTriangles[i].m_vertexes[2] = pTriangle->m_vertexIndices[2];

		pTriangles[i].m_normals[0] = vector3(pTriangle->m_vertexNormals[0][0],pTriangle->m_vertexNormals[0][1],pTriangle->m_vertexNormals[0][2]);
		pTriangles[i].m_normals[1] = vector3(pTriangle->m_vertexNormals[1][0],pTriangle->m_vertexNormals[1][1],pTriangle->m_vertexNormals[1][2]);
		pTriangles[i].m_normals[2] = vector3(pTriangle->m_vertexNormals[2][0],pTriangle->m_vertexNormals[2][1],pTriangle->m_vertexNormals[2][2]);


		pTriangles[i].m_texcoords[0] = vector2(pTriangle->m_s[0],pTriangle->m_t[0]);
		pTriangles[i].m_texcoords[1] = vector2(pTriangle->m_s[1],pTriangle->m_t[1]);
		pTriangles[i].m_texcoords[2] = vector2(pTriangle->m_s[2],pTriangle->m_t[2]);

		pPtr += sizeof(MS3DTriangle);
	}

	u32 nGroups = *(u16*)pPtr;
	m_meshes.resize(nGroups);
	pPtr += sizeof(u16);

	u32 vbuffer_size = 0;

	u32** triangle_indexes = new u32*[nGroups];

	string subset_name;

	for(i=0;i<nGroups;i++)
	{
		pPtr += sizeof(u8);
		subset_name = (const char*)pPtr;
		pPtr += 32;

		u16 nTriangles = *(u16*)pPtr;
		pPtr += sizeof(u16);
		triangle_indexes[i] = new u32[nTriangles];
		for(int j=0;j<nTriangles;j++)
		{
			triangle_indexes[i][j] = *(u16*)pPtr;
			pPtr += sizeof(u16);
		}

		char materialIndex = *(char*)pPtr;
		pPtr += sizeof(u8);

		m_meshes[i].m_material_id = materialIndex;
		m_meshes[i].m_pr_count = nTriangles;
		m_meshes[i].m_first_pr = vbuffer_size;
		m_meshes[i].m_indexed = false;

		m_subsetes[subset_name] = &(m_meshes[i]);

		vbuffer_size += nTriangles;
	}

	m_vbuffer = m_render->create_vbuffer(usage_static,vf_xyz|vf_normal|vf_texture1,sizeof(mdl_vertex),sizeof(mdl_vertex)*vbuffer_size*3);
	mdl_vertex* buf = (mdl_vertex*)m_vbuffer->lock(lock_write);
	for(i=0;i<m_meshes.size();i++)
	{
		m_meshes[i].m_min = vector3(1000000.0f,1000000.0f,1000000.0f);
		m_meshes[i].m_max = vector3(-1000000.0f,-1000000.0f,-1000000.0f);

		for(u32 j=0;j<m_meshes[i].m_pr_count;j++)
		{
			mdl_triangle* t = &(pTriangles[triangle_indexes[i][j]]);

			if(pVertices[t->m_vertexes[0]].x < m_meshes[i].m_min.x)
				m_meshes[i].m_min.x = pVertices[t->m_vertexes[0]].x;
			if(pVertices[t->m_vertexes[0]].x > m_meshes[i].m_max.x)
				m_meshes[i].m_max.x = pVertices[t->m_vertexes[0]].x;

			if(pVertices[t->m_vertexes[0]].y < m_meshes[i].m_min.y)
				m_meshes[i].m_min.y = pVertices[t->m_vertexes[0]].y;
			if(pVertices[t->m_vertexes[0]].y > m_meshes[i].m_max.y)
				m_meshes[i].m_max.y = pVertices[t->m_vertexes[0]].y;

			if(pVertices[t->m_vertexes[0]].z < m_meshes[i].m_min.z)
				m_meshes[i].m_min.z = pVertices[t->m_vertexes[0]].z;
			if(pVertices[t->m_vertexes[0]].z > m_meshes[i].m_max.z)
				m_meshes[i].m_max.z = pVertices[t->m_vertexes[0]].z;

			if(pVertices[t->m_vertexes[1]].x < m_meshes[i].m_min.x)
				m_meshes[i].m_min.x = pVertices[t->m_vertexes[1]].x;
			if(pVertices[t->m_vertexes[1]].x > m_meshes[i].m_max.x)
				m_meshes[i].m_max.x = pVertices[t->m_vertexes[1]].x;

			if(pVertices[t->m_vertexes[1]].y < m_meshes[i].m_min.y)
				m_meshes[i].m_min.y = pVertices[t->m_vertexes[1]].y;
			if(pVertices[t->m_vertexes[1]].y > m_meshes[i].m_max.y)
				m_meshes[i].m_max.y = pVertices[t->m_vertexes[1]].y;

			if(pVertices[t->m_vertexes[1]].z < m_meshes[i].m_min.z)
				m_meshes[i].m_min.z = pVertices[t->m_vertexes[1]].z;
			if(pVertices[t->m_vertexes[1]].z > m_meshes[i].m_max.z)
				m_meshes[i].m_max.z = pVertices[t->m_vertexes[1]].z;

			if(pVertices[t->m_vertexes[2]].x < m_meshes[i].m_min.x)
				m_meshes[i].m_min.x = pVertices[t->m_vertexes[2]].x;
			if(pVertices[t->m_vertexes[2]].x > m_meshes[i].m_max.x)
				m_meshes[i].m_max.x = pVertices[t->m_vertexes[2]].x;

			if(pVertices[t->m_vertexes[2]].y < m_meshes[i].m_min.y)
				m_meshes[i].m_min.y = pVertices[t->m_vertexes[2]].y;
			if(pVertices[t->m_vertexes[2]].y > m_meshes[i].m_max.y)
				m_meshes[i].m_max.y = pVertices[t->m_vertexes[2]].y;

			if(pVertices[t->m_vertexes[2]].z < m_meshes[i].m_min.z)
				m_meshes[i].m_min.z = pVertices[t->m_vertexes[2]].z;
			if(pVertices[t->m_vertexes[2]].z > m_meshes[i].m_max.z)
				m_meshes[i].m_max.z = pVertices[t->m_vertexes[2]].z;

			buf[0].m_pos	= pVertices[t->m_vertexes[0]];
			buf[0].m_normal = t->m_normals[0];
			buf[0].m_tex	= t->m_texcoords[0];
			buf[1].m_pos	= pVertices[t->m_vertexes[1]];
			buf[1].m_normal = t->m_normals[1];
			buf[1].m_tex	= t->m_texcoords[1];
			buf[2].m_pos	= pVertices[t->m_vertexes[2]];
			buf[2].m_normal = t->m_normals[2];
			buf[2].m_tex	= t->m_texcoords[2];
			buf+=3;
		}
	}
	m_vbuffer->unlock();

	u32 nMaterials = *(u16*)pPtr;
	m_materials.resize(nMaterials);

	if(nMaterials>0)
	{
		pPtr += sizeof(u16);
		for(i=0;i<nMaterials;i++)
		{
			MS3DMaterial *pMaterial = (MS3DMaterial*)pPtr;
			m_materials[i].m_material.ambient = color(pMaterial->m_ambient[0],pMaterial->m_ambient[1],pMaterial->m_ambient[2],pMaterial->m_ambient[3]);
			m_materials[i].m_material.diffuse = color(pMaterial->m_diffuse[0],pMaterial->m_diffuse[1],pMaterial->m_diffuse[2],pMaterial->m_diffuse[3]);
			m_materials[i].m_material.specular = color(pMaterial->m_specular[0],pMaterial->m_specular[1],pMaterial->m_specular[2],pMaterial->m_specular[3]);
			m_materials[i].m_material.emission = color(pMaterial->m_emissive[0],pMaterial->m_emissive[1],pMaterial->m_emissive[2],pMaterial->m_emissive[3]);

			m_materials[i].m_material.shininess = pMaterial->m_shininess;
			
			if(strcmp(pMaterial->m_texture,"")!=0)
			{
				string path = pathmngr::get_inst().get_texture(pMaterial->m_texture);
				m_materials[i].m_texture = m_render->create_texture(path.c_str());
			}
			else
				m_materials[i].m_texture = 0;

			pPtr += sizeof(MS3DMaterial);
		}
	}

	delete[] pBuffer;
	delete[] pVertices;
	delete[] pTriangles;
	
	for(i=0;i<m_meshes.size();i++)
		delete[] triangle_indexes[i];
	delete[] triangle_indexes;

	return;
}

void model::load_ogrexml(const char* _fname)
{
	release();

	xml_document doc;
	doc.parse_file(_fname);

	xml_node& sg = doc["mesh"]["sharedgeometry"];

	u32 vb_size = sg.attr_int("vertexcount");

	u32 vf = 0;

	for(u32 m=0;m<sg.child_count();m++)
	{
		xml_node& vb = sg[m];
		if(string(vb.name())!="vertexbuffer")
			continue;
	
		if(vb.attr_bool("positions"))
			vf |= vf_xyz;
		if(vb.attr_bool("normals"))
			vf |= vf_normal;
		if(vb.attr_bool("texture_coords"))
			vf |= vf_texture1;
	}

	m_vertexes.resize(vb_size);
	m_animvtxs.resize(vb_size);

	for(u32 m=0;m<sg.child_count();m++)
	{
		xml_node& vb = sg[m];
		if(string(vb.name())!="vertexbuffer")
			continue;

		u32 i,vcount = 0;

		for(i=0;i<vb.child_count();i++)
		{
			if(i>=vb_size)
				LOG_FATAL("Wrong vertex buffer size for Ogre XML.");
			if(string(vb[i].name())!="vertex")
				continue;
			u32 j = vcount++;
			if(vb.attr_bool("positions"))
			{
				m_vertexes[j].m_pos.x = vb[i]["position"].attr_float("x");
				m_vertexes[j].m_pos.y = vb[i]["position"].attr_float("y");
				m_vertexes[j].m_pos.z = vb[i]["position"].attr_float("z");
			}
			if(vb.attr_bool("normals"))
			{
				m_vertexes[j].m_normal.x = vb[i]["normal"].attr_float("x");
				m_vertexes[j].m_normal.y = vb[i]["normal"].attr_float("y");
				m_vertexes[j].m_normal.z = vb[i]["normal"].attr_float("z");
			}
			if(vb.attr_bool("texture_coords"))
			{
				m_vertexes[j].m_tex.x = vb[i]["texcoord"].attr_float("u");
				m_vertexes[j].m_tex.y = vb[i]["texcoord"].attr_float("v");
			}
		}
	}

	m_vbuffer = m_render->create_vbuffer(usage_static,vf,sizeof(mdl_vertex),sizeof(mdl_vertex)*vb_size);
	mdl_vertex* vbuffer = (mdl_vertex*)m_vbuffer->lock(lock_write);

	for(u32 i=0;i<vb_size;i++)
	{
		m_animvtxs[i] = m_vertexes[i];
		memcpy(vbuffer+i,&(m_vertexes[i]),sizeof(mdl_vertex));
	}

	m_vbuffer->unlock();

	if(doc["mesh"].check_child("materials"))
	{
		xml_node& mats = doc["mesh"]["materials"];
		u32 matcnt = mats.attr_int("count");
		m_materials.resize(matcnt);

		matcnt = 0;

		for(u32 i=0;i<mats.child_count();i++)
		{
			if(string(mats[i].name())!="material")
				continue;
			u32 j = matcnt++;
			m_materials[j].m_material.ambient.r = mats[j]["ambient"].attr_float("r");
			m_materials[j].m_material.ambient.g = mats[j]["ambient"].attr_float("g");
			m_materials[j].m_material.ambient.b = mats[j]["ambient"].attr_float("b");
			m_materials[j].m_material.ambient.a = 1.0f;
			m_materials[j].m_material.diffuse.r = mats[j]["diffuse"].attr_float("r");
			m_materials[j].m_material.diffuse.g = mats[j]["diffuse"].attr_float("g");
			m_materials[j].m_material.diffuse.b = mats[j]["diffuse"].attr_float("b");
			m_materials[j].m_material.diffuse.a = 1.0f;
			m_materials[j].m_material.specular.r = mats[j]["specular"].attr_float("r");
			m_materials[j].m_material.specular.g = mats[j]["specular"].attr_float("g");
			m_materials[j].m_material.specular.b = mats[j]["specular"].attr_float("b");
			m_materials[j].m_material.specular.a = 1.0f;
			m_materials[j].m_material.emission.r = mats[j]["emission"].attr_float("r");
			m_materials[j].m_material.emission.g = mats[j]["emission"].attr_float("g");
			m_materials[j].m_material.emission.b = mats[j]["emission"].attr_float("b");
			m_materials[j].m_material.emission.a = 1.0;
			m_materials[j].m_material.shininess = 0.0f;
			if(mats[j].check_child("texture"))
			{
				string path = pathmngr::get_inst().get_texture(mats[j]["texture"].attr_str("file"));
				m_materials[j].m_texture = m_render->create_texture(path.c_str());
			}
			else
				m_materials[j].m_texture = 0;
		}
	}

	u32 ibsize = 0;
	u32 meshcnt = 0;

	xml_node& sm = doc["mesh"]["submeshes"];

	for(u32 i=0;i<sm.child_count();i++)
	{
		if(string(sm[i].name())=="submesh")
		{
			meshcnt++;
			ibsize+= sm[i]["faces"].attr_int("count")*3;
		}
	}

	m_ibuffer = m_render->create_ibuffer(usage_static,ibsize*2);
	u16* ibuffer = (u16*)m_ibuffer->lock(lock_write);

	m_meshes.resize(meshcnt);
	meshcnt = 0;
	ibsize = 0;

	for(u32 i=0;i<sm.child_count();i++)
	{
		if(string(sm[i].name())!="submesh")
			continue;
		u32 j = meshcnt++;
		m_meshes[j].m_material_id = sm[i].attr_int("material");
		m_meshes[j].m_indexed = true;
		m_meshes[j].m_first_pr = ibsize;
		m_meshes[j].m_pr_count = sm[i]["faces"].attr_int("count");

		for(u32 k=0;k<m_meshes[j].m_pr_count;k++)
		{
			if(string(sm[i]["faces"][k].name())!="face")
				continue;
			xml_node& face = sm[i]["faces"][k];
			ibuffer[ibsize++] = face.attr_int("v1");
			ibuffer[ibsize++] = face.attr_int("v2");
			ibuffer[ibsize++] = face.attr_int("v3");
		}
	}
	m_ibuffer->unlock();

	if(doc["mesh"].check_child("boneassignments"))
	{
		xml_node& wn = doc["mesh"]["boneassignments"];

		u32 bacnt = 0;

		for(u32 i=0;i<wn.child_count();i++)
		{
			if(string(wn[i].name())!="vertexboneassignment")
				continue;
			bacnt++;
		}

		m_weights.resize(bacnt);
		bacnt=0;

		for(u32 i=0;i<wn.child_count();i++)
		{
			if(string(wn[i].name())!="vertexboneassignment")
				continue;
			u32 n = bacnt++;
			m_weights[n].m_vertex = wn[i].attr_int("vertexindex");
			m_weights[n].m_bone = wn[i].attr_int("boneindex");
			m_weights[n].m_value = wn[i].attr_float("weight");
		}
	}
}

void model::load_ogreani(const char* _fname)
{
	/*xml_document doc;
	doc.parse_file(_fname);

	xml_node& bn = doc["skeleton"]["bones"];
	u32 bonecnt = 0;

	for(u32 i=0;i<bn.child_count();i++)
	{
		if(string(bn[i].name())!="bone")
			continue;
		bonecnt++;
	}

	m_bones.resize(bonecnt);
	bonecnt=0;

	for(u32 i=0;i<bn.child_count();i++)
	{
		if(string(bn[i].name())!="bone")
			continue;
		u32 n = bonecnt++;
		vector3 pos(bn[i]["position"].attr_float("x"),bn[i]["position"].attr_float("y"),bn[i]["position"].attr_float("z"));
		vector3 rot(bn[i]["rotation"]["axis"].attr_float("x"),bn[i]["rotation"]["axis"].attr_float("y"),bn[i]["rotation"]["axis"].attr_float("z"));
		float ang = bn[i]["rotation"].attr_float("angle");
		matrix4 mtx_t;
		mtx_t.translate(pos);
		quater q(rot,ang);
		matrix4 mtx_r = (matrix4)q;
		m_bones[n].m_matrix = mtx_t*mtx_r;
	}

	xml_node& bhn = doc["skeleton"]["bonehierarchy"];

	for(u32 i=0;i<bhn.child_count();i++)
	{
		if(string(bhn[i].name())!="boneparent")
			continue;
		string bone_name = bhn[i].attr_str("bone");
		mdl_bone* bone=0;
		for(u32 j=0;j<bn.child_count();j++)
		{
			if(string(bn[j].name())!="bone")
				continue;
			if(string(bn[j].attr_str("name"))==bone_name)
			{
				bone = &(m_bones[bn[j].attr_int("id")]);
				break;
			}
		}
		if(bone==0)
		{
			LOG_FATAL("Can't find bone '%s'",bone_name.c_str());
		}
		string parent_name = bhn[i].attr_str("parent");
		if(parent_name=="root")
		{
			bone->m_parent = 0;
			m_boneroot = bone;
			break;
		}
		else
		{
			for(u32 j=0;j<bn.child_count();j++)
			{
				if(string(bn[j].name())!="bone")
					continue;
				if(string(bn[j].attr_str("name"))==parent_name)
				{
					bone->m_parent = &(m_bones[bn[j].attr_int("id")]);
					if(bone->m_parent==0)
					{
						LOG_FATAL("Can't find bone '%s'",parent_name.c_str());
					}
					break;
				}
			}
		}
	}
	if(m_boneroot==0)
	{
		LOG_FATAL("Must set root bone for animation.");
	}
	
	xml_node& an = doc["skeleton"]["animations"];
	u32 anicnt = 0;

	for(u32 i=0;i<an.child_count();i++)
	{
		if(string(an[i].name())!="animation")
			continue;
		anicnt++;
	}

	anicnt=0;

	for(u32 i=0;i<an.child_count();i++)
	{
		if(string(an[i].name())!="animation")
			continue;
		
		u32 j =  anicnt++;

		string ani_name = an[i].attr_str("name");

		m_animations[ani_name] = mdl_animation();

		mdl_animation& ani = m_animations[ani_name];

		ani.m_length = an[i].attr_float("length");

		xml_node& tn = an[i]["tracks"];
		u32 tracksnum=0;

		for(u32 k=0;k<tn.child_count();k++)
		{
			if(string(tn[k].name())!="track")
				continue;
			tracksnum++;
		}

		ani.m_traks.resize(tracksnum);
		tracksnum=0;

		for(u32 k=0;k<tn.child_count();k++)
		{
			if(string(tn[k].name())!="track")
				continue;

			u32 n = tracksnum++;

			string bonename = tn[k].attr_str("bone");

			ani.m_traks[n].m_boneid = -1;

			for(u32 l=0;l<bn.child_count();l++)
			{
				if(bonename == bn[l].attr_str("name"))
				{
					ani.m_traks[k].m_boneid = bn[l].attr_int("id");
					break;
				}
			}

			if(ani.m_traks[n].m_boneid==-1)
			{
				LOG_FATAL("Can't find bone '%s'",bonename.c_str());
			}

			xml_node& fn = tn[k]["keyframes"];
			u32 framenum = 0;

			for(u32 m=0;m<fn.child_count();m++)
			{
				if(string(fn[m].name())!="keyframe")
					continue;
				framenum++;
			}

			ani.m_traks[n].m_frames.resize(framenum);
			framenum=0;

			for(u32 m=0;m<fn.child_count();m++)
			{
				if(string(fn[m].name())!="keyframe")
					continue;
				
				u32 z = framenum++;

				mdl_keyframe& kf = ani.m_traks[n].m_frames[z];
				kf.m_time = fn[m].attr_float("time");

				kf.m_sclmtx.identity();

				vector3 pos(fn[m]["translate"].attr_float("x"),fn[m]["translate"].attr_float("y"),fn[m]["translate"].attr_float("z"));
				kf.m_posmtx.translate(pos);

				vector3 rot(fn[m]["rotate"]["axis"].attr_float("x"),fn[m]["rotate"]["axis"].attr_float("y"),fn[m]["rotate"]["axis"].attr_float("z"));
				float angle = fn[m]["rotate"].attr_float("angle");

				quater q(rot,angle);

				kf.m_rotmtx = (matrix4)q;
			}
		}
	}*/
}

float model::set_anim(const char* _name)
{
	if(m_animations.find(string(_name))==m_animations.end())
	{
		LOG_FATAL("Can't find animation '%s'",_name);
	}
	m_currani = &(m_animations[string(_name)]);
	set_time(0.0f);
	return m_currani->m_length;
}

void model::set_time(float _time)
{
	
}

void model::draw_static()
{
	for(u32 i=0;i<m_meshes.size();i++)
	{
		mdl_mesh* mesh = &m_meshes[i];
		int id = m_meshes[i].m_material_id;
		if(id!=-1)
		{
			m_render->set_material(m_materials[id].m_material);
			texture* tex = m_materials[id].m_texture;
			if(tex)
				m_render->set_texture(0,tex);
			else
				m_render->set_texture(0,0);
		}
		else
		{
			material m;
			m.ambient = color(0.3f,0.3f,0.3f,1.0f);
			m.diffuse = color(0.3f,0.3f,0.3f,1.0f);
			m.emission = color(0.3f,0.3f,0.3f,1.0f);
			m.specular = color(0.3f,0.3f,0.3f,1.0f);
			m.shininess = 1.0f;
			m_render->set_material(m);
			m_render->set_texture(0,0);
		}
		m_render->set_cullmode(cullmode_none);
		m_render->set_vbuffer(m_vbuffer);
		if(mesh->m_indexed)
		{
			m_render->set_ibuffer(m_ibuffer);
			m_render->draw_ibuffer(pr_triangles,mesh->m_pr_count*3,mesh->m_first_pr,mesh->m_pr_count);
		}
		else
			m_render->draw_vbuffer(pr_triangles,mesh->m_first_pr*3,mesh->m_pr_count);
		}
}

mdl_mesh* model::get_subset(const char* _name)
{
	return m_subsetes[_name];
}

mdl_mesh* model::get_subset(string _name)
{
	return get_subset(_name.c_str());
}

void model::draw_subset(string _name)
{
	draw_subset(_name.c_str());
}

void model::draw_subset(const char* _name)
{
	mdl_mesh* mesh = get_subset(_name);

	int id = mesh->m_material_id;
	if(id!=-1)
	{
		m_render->set_material(m_materials[id].m_material);
		texture* tex = m_materials[id].m_texture;
		if(tex)
			m_render->set_texture(0,tex);
		else
			m_render->set_texture(0,0);
	}
	else
	{
		material m;
		m.ambient = color(0.3f,0.3f,0.3f,1.0f);
		m.diffuse = color(0.3f,0.3f,0.3f,1.0f);
		m.emission = color(0.3f,0.3f,0.3f,1.0f);
		m.specular = color(0.3f,0.3f,0.3f,1.0f);
		m.shininess = 1.0f;
		m_render->set_material(m);
		m_render->set_texture(0,0);
	}
	m_render->set_cullmode(cullmode_none);
	m_render->set_vbuffer(m_vbuffer);
	if(mesh->m_indexed)
	{
		m_render->set_ibuffer(m_ibuffer);
		m_render->draw_ibuffer(pr_triangles,mesh->m_pr_count*3,mesh->m_first_pr,mesh->m_pr_count);
	}
	else
		m_render->draw_vbuffer(pr_triangles,mesh->m_first_pr*3,mesh->m_pr_count);
}

void model::draw_shader(effect* _fx,const char* _tex_param,const char* _col_param)
{
	for(u32 i=0;i<m_meshes.size();i++)
	{
		int id = m_meshes[i].m_material_id;
		if(id!=-1)
		{
			if(_col_param)
			{
				_fx->set_param(prog_vertex,_col_param,m_materials[id].m_material.diffuse.v,4);
			}
			texture* tex = m_materials[id].m_texture;
			if(tex&&_tex_param)
			{
				_fx->set_param(prog_vertex,_tex_param,tex);
			}
		}
		m_render->set_cullmode(cullmode_cw);
		m_render->set_vbuffer(m_vbuffer);
		m_render->draw_vbuffer(pr_triangles,m_meshes[i].m_first_pr*3,m_meshes[i].m_pr_count);
	}
}
